<template>
  <div class="page-controller">
    <!-- 查询条件区 -->
    <FISearchForm
      class="box-radius2"
      ref="ruleFormRef"
      :id="`inqu_${tableId}`"
      v-model:form-value="state.query"
      :table-column="columns"
      :wrapperSpan="searchWrapperSpan"
      @submit="searchFn"
    >
      <el-col :span="searchWrapperSpan" class="flex-center">
        <FIFormItem prop="compName" label="组件名称">
          <FIInput v-model="state.query.compName" clearable />
        </FIFormItem>
      </el-col>
      <el-col :span="searchWrapperSpan" class="flex-center">
        <FIFormItem prop="compType" label="组件类型">
          <FISelect
            v-model="state.query.compType"
            valueCustom="value"
            :options="[
              { value: '1', label: '消息类' },
              { value: '2', label: '通知类' },
            ]"
            clearable
          />
        </FIFormItem>
      </el-col>
      <el-col :span="searchWrapperSpan" class="flex-center">
        <FIFormItem prop="bizType" label="业务分类">
          <FISelect
            v-model="state.query.bizType"
            valueCustom="value"
            :options="[
              { value: '1', label: '业务分类1' },
              { value: '2', label: '业务分类2' },
            ]"
            clearable
          />
        </FIFormItem>
      </el-col>
    </FISearchForm>
    <!-- 查询结果列表区 -->
    <FITable
      ref="tableRef"
      class="box-radius2 margin-top20"
      title="记录集"
      :id="`result_${tableId}`"
      :readonly="true"
      :data="state.dataList"
      check-mode=""
      primaryKey="compId"
      v-model:columns="columns"
      :isLoading="isTableLoading"
      :insertable="false"
      :show-save-model="false"
      :saveSuccessful="saveSuccessful"
      :pageConfig="pageConfig"
      @table-refresh="searchFn"
      @selection-change="handleSelectionChange"
      @size-change="handleSizeChange"
      @current-page-change="handleCurrentChange"
      @action-click="handleAction"
    >
      <template #headerBtn>
        <FIButton id="insert" border @click="showModelFn('add')"></FIButton>
      </template>
      <template #picBase64="{ scope }">
        <img
          v-if="scope.row.picBase64"
          class="pic-class"
          :src="scope.row.picBase64"
          @click="showImageDialog(scope.row)"
        />
        <!-- <el-image
          style="width: 100px; height: 100px"
          :src="scope.row.picBase64"
          :zoom-rate="1.2"
          :max-scale="7"
          :min-scale="0.2"
          :preview-src-list="[scope.row.picBase64]"
          :initial-index="0"
          fit="cover"
          :z-index="999"
        /> -->
        <!-- <div>{{ scope.row.picBase64 }}</div> -->
      </template>
    </FITable>
    <el-image-viewer
      v-if="state.tempRowData.showPic"
      class="card-item__img"
      :url-list="[state.tempRowData.picBase64]"
      :zoom-rate="1.2"
      @close="state.tempRowData.showPic = false"
    >
    </el-image-viewer>

    <FIModel
      v-model="editVisible"
      :title="modelType == 'add' ? '新增' : '编辑'"
      width="600"
      :confirmLoading="state.confirmLoading"
      @confirm="handleAdd"
    >
      <FIForm class="comp-model">
        <FIFormItem prop="compType" label="组件名称">
          <FIInput v-model="state.rowObj.compName" clearable />
        </FIFormItem>
        <FIFormItem prop="compType" label="组件类型">
          <FISelect
            v-model="state.rowObj.compType"
            valueCustom="value"
            :options="[
              { value: '1', label: '消息类' },
              { value: '2', label: '指标类' },
            ]"
            clearable
          />
        </FIFormItem>
        <FIFormItem prop="bizType" label="业务分类">
          <FISelect
            v-model="state.rowObj.bizType"
            valueCustom="value"
            :options="[
              { value: '1', label: '业务分类1' },
              { value: '2', label: '业务分类2' },
            ]"
            clearable
          />
        </FIFormItem>
        <FIFormItem prop="compRows" label="占用行数">
          <FIInputNumber v-model="state.rowObj.compRows" :min="1" :max="12" controls-position="right" />
        </FIFormItem>
        <FIFormItem prop="compCols" label="占用列数">
          <FIInputNumber v-model="state.rowObj.compCols" :min="1" :max="12" controls-position="right" />
        </FIFormItem>
        <FIFormItem prop="picBase64" label="缩略图">
          <el-upload
            class="avatar-uploader"
            action="#"
            :show-file-list="false"
            :http-request="handleUpload"
            :on-success="handleSuccess"
            :on-error="handleError"
            list-type="picture-card"
            :on-preview="handlePictureCardPreview"
            :on-remove="handleRemove"
            :before-upload="beforeAvatarUploadOther"
          >
            <img
              v-if="imageUrl || state.rowObj.picBase64"
              :src="modelType == 'add' ? imageUrl : state.rowObj.picBase64"
              class="avatar"
            />
            <FIButton v-else border prefixIcon="icon-shangchuan">点击上传</FIButton>
            <template #tip>
              <div class="el-upload__tip">请上传png/jpg文件，且不超过500KB.</div>
            </template>
          </el-upload>
        </FIFormItem>
        <FIFormItem prop="vueRoute" label="组件路由">
          <FIInput v-model="state.rowObj.vueRoute" clearable />
        </FIFormItem>
        <FIFormItem prop="remark" label="描述">
          <FIInput v-model="state.rowObj.remark" :rows="3" type="textarea" />
        </FIFormItem>
      </FIForm>
    </FIModel>
    <FIModel title="预览" v-model="state.showPreview">
      <component :is="dynamicComponent" />
    </FIModel>
  </div>
</template>
<script lang="ts" setup>
// import CommonNav from '../components/CommonNav.vue'

import { reactive, onMounted, ref, shallowRef } from 'vue'
import FISearchForm from '@/components/FISearchForm.vue'
import FIFormItem from '@/components/FIFormItem.vue'
import FIModel from '@/components/FIModel.vue'
import FIInput from '@/components/FIInput.vue'
import FITable from '@/components/FITable/index.vue'
import FISelect from '@/components/FISelect/index.vue'
import { apiRequestPost } from '@/api/globalApi.js'
import { useMessage } from '@/hooks/message' // 通用message消息提示框
import type { PageConfig, Column } from '@/types/components'
import { useRoute } from 'vue-router'
import { initSearchData } from '@/utils/common'
import { getQueryTableCache } from '@/utils/cacheUtils'
import { getCurrentInstance } from 'vue'
import FIInputNumber from '@/components/FIInputNumber.vue'
import type { UploadProps } from 'element-plus'

const { proxy } = getCurrentInstance() // 获取当前组件实例上下文
// 路由对象
const route = useRoute()
// el-col span栅格占据的列数
const searchWrapperSpan = 8
// 表格是否显示加载中
const isTableLoading = ref(false)
// 页面编码
const tableId = 'GMOPComp'
// 保存成功按钮状态，默认不展示底部保存，取消按钮
const saveSuccessful = ref(false)
const editVisible = ref(false)
const modelType = ref('add')
// 表格对象
const tableRef = ref(null)
const state = reactive({
  // 查询条件
  query: {
    compName: '',
    compType: '',
    bizType: '',
    current: 1,
    size: 10,
  },
  // 表格数据
  dataList: [],
  rowObj: {
    compName: '',
    compType: '',
    bizType: '',
    compRows: 1,
    compCols: 1,
    picBase64: '',
    vueRoute: '',
    remark: '',
    _isNew: 0,
  },
  confirmLoading: false,
  fileList: [],
  tempRowData: {
    showPic: false,
    picBase64: '',
  },
  showPreview: false,
  previewComp: '',
})

// 页面配置
const pageConfig: PageConfig = reactive({
  total: 0, // 总条数
  currentPage: 1, // 当前页码
})
// 表格列数据
const columns: Column[] = reactive([
  {
    label: '组件名称',
    prop: 'compName',
    align: 'center',
    minWidth: '150',
    editable: true,
    required: true,
  },

  {
    label: '组件类型', // 列名
    prop: 'compType', // 字段名称 对应列内容的字段名， 也可以使用 property属性
    align: 'center', // 列内容对齐方式
    minWidth: '140', // 列宽
    editable: true, // 是否可编辑
    editType: 'select', // 编辑类型
    editConfig: {
      options: [
        { value: '1', label: '消息类' },
        { value: '2', label: '通知类' },
      ],
    },
  },
  {
    label: '业务分类', // 列名
    prop: 'bizType', // 字段名称 对应列内容的字段名， 也可以使用 property属性
    align: 'center', // 列内容对齐方式
    minWidth: '140', // 列宽
    editType: 'select', // 编辑类型
    editConfig: {
      options: [
        { value: '1', label: '业务分类1' },
        { value: '2', label: '业务分类2' },
      ],
    },
  },
  {
    label: '占用行数',
    prop: 'compRows',
    align: 'center',
    minWidth: '180',
  },
  {
    label: '占用列数',
    prop: 'compCols',
    align: 'center',
    minWidth: '180',
  },
  {
    label: '缩略图',
    prop: 'picBase64',
    align: 'center',
    minWidth: '120',
  },
  {
    label: '组件路由',
    prop: 'vueRoute',
    align: 'center',
    width: '150',
  },
  {
    label: '描述',
    prop: 'remark',
    align: 'center',
    minWidth: '130',
  },
  {
    label: '创建人',
    prop: 'recCreator',
    align: 'center',
    minWidth: '120',
  },
  {
    label: '创建时间',
    prop: 'recCreateTime',
    align: 'center',
    minWidth: '160',
    editType: 'time-picker',
  },
  {
    label: '',
    prop: 'action',
    actionConfig: [
      { id: 'edit', type: 'edit' },
      { id: 'delete', type: 'delete' },
      { id: 'preview', type: 'preview' },
    ],
  },
])
// 选中列表集合
const checkedRows = ref([])
// 选中列表集合值改变回调函数
const handleSelectionChange = (e) => {
  checkedRows.value = e
}
// 分页大小改变回调函数
const handleSizeChange = (e) => {
  pageConfig.pageSize = e
  pageConfig.currentPage = 1
  searchFn()
}
// 分页页码改变回调函数
const handleCurrentChange = (e) => {
  pageConfig.currentPage = e
  searchFn('page')
}

// 搜索查询函数
const searchFn = (type?: string, columnsVal?: any) => {
  // 页面搜索数据组装
  const obj = initSearchData(type, columnsVal, columns, state.query)
  state.query = obj.queryData
  columns.values = obj.columns
  if (type == 'page') {
    state.query.current = pageConfig.currentPage
  } else {
    pageConfig.currentPage = 1
    state.query.current = 1
  }
  isTableLoading.value = true
  if (pageConfig.pageSize) state.query.size = pageConfig.pageSize
  const apiUrl = proxy.$Button_api('query', route.name)
  apiRequestPost(apiUrl, state.query)
    .then((res) => {
      isTableLoading.value = false
      if (res.data.success) {
        state.dataList = res.data.data.result
        pageConfig.pageSize = Number(res.data.data.size)
        pageConfig.total = Number(res.data.data.count)
      }
    })
    .catch((error: any) => {
      isTableLoading.value = false
      // 处理错误
    })
}
// table保存提交
const handleAdd = () => {
  state.confirmLoading = true
  const apiUrl = proxy.$Button_api('insert', route.name)
  apiRequestPost(apiUrl, state.rowObj)
    .then((res) => {
      state.confirmLoading = false
      if (res.data.success) {
        editVisible.value = false
        searchFn()
      }
    })
    .catch((error: any) => {
      state.confirmLoading = false
    })
}
// 删除函数
const deleteRow = (item) => {
  isTableLoading.value = true
  const apiUrl = proxy.$Button_api('delete', route.name)
  apiRequestPost(apiUrl, item)
    .then((res) => {
      isTableLoading.value = false
      searchFn()
    })
    .catch((error: any) => {
      isTableLoading.value = false
    })
}
const dynamicComponent = shallowRef(null)
const handleAction = async (item, rowData) => {
  if (item.type === 'edit') {
    editVisible.value = true
    state.rowObj = rowData
    showModelFn('edit')
  } else if (item.type === 'delete') {
    deleteRow(rowData)
  } else if (item.type === 'preview') {
    state.previewComp = rowData.vueRoute
    dynamicComponent.value = await loadComponent(state.previewComp)
    state.showPreview = true
  }
}
// 动态加载组件的函数
const loadComponent = async (componentName) => {
  try {
    const module = await import(`../components/${componentName}.vue`)
    return module.default
  } catch (error) {
    useMessage().error('预览组件加载失败！')
  }
}

const showModelFn = (type = 'add') => {
  editVisible.value = true
  modelType.value = type
  if (type === 'add') {
    state.rowObj = {
      compName: '',
      compType: '',
      bizType: '',
      compRows: '',
      compCols: '',
      picBase64: '',
      vueRoute: '',
      remark: '',
      _isNew: 1,
    }
  } else {
    state.rowObj._isNew = 0
  }
}
const showImageDialog = (data) => {
  state.tempRowData.picBase64 = data.picBase64
  state.tempRowData.showPic = true
}
const handleUpload = async (params) => {
  const formData = new FormData()
  formData.append('images', params.file)
}
const imageUrl = ref('')
const handleSuccess = (response, file, fileList) => {
  console.log('上传成功--1', response)
  console.log('上传成功--2', file)

  state.fileList = fileList
  imageUrl.value = URL.createObjectURL(file.raw!)
  console.log(imageUrl.value, '上传成功--3', fileList)
  const reader = new FileReader()
  reader.readAsDataURL(file.raw)
  reader.onload = () => {
    // base64String = reader.result;
    console.log('上传成功--reader', reader)
    state.rowObj.picBase64 = reader.result as string
    // 在这里调用上传到后端的函数，将 base64String.value 上传到后端
  }
  state.fileList = fileList
}
const dialogImageUrl = ref('')
const dialogVisible = ref(false)

const handleRemove: UploadProps['onRemove'] = (uploadFile, uploadFiles) => {
  imageUrl.value = ''
  console.log(uploadFile, uploadFiles)
}

const handlePictureCardPreview: UploadProps['onPreview'] = (uploadFile) => {
  dialogImageUrl.value = uploadFile.url!
  dialogVisible.value = true
}
const handleError = (error, file, fileList) => {
  console.log('文件上传失败', error)
}
//上传文件和上传附件之前的校验
const beforeAvatarUploadOther = (file) => {
  const isJPG = file.type === 'image/jpeg'
  const isPNG = file.type === 'image/png'
  const isLt500k = file.size / 1024 / 1024 < 0.5

  if (!isJPG && !isPNG) {
    useMessage().error('上传图片只能是 JPG/PNG 格式！')
    return false
  }
  if (!isLt500k) {
    useMessage().error('上传图片大小不能超过 500KB！')
    return false
  }
  return true
}
onMounted(() => {
  // 获取查询条件缓存
  const { cachedQuery, cachedColumns } = getQueryTableCache(route.path, tableId, state.query, columns.values)
  if (cachedQuery) state.query = cachedQuery
  searchFn()
})
</script>
<style lang="less" scoped>
.avatar-uploader .avatar {
  width: 178px;
  height: 178px;
  display: block;
}
.pic-class {
  width: 85px;
  height: 60px;
}
.el-upload__tip {
  font-size: 12px;
  color: #9f9f9f;
}
.comp-model .oy-form-item {
  width: 100%;
  ::v-deep(.el-input .el-input__wrapper) {
    width: 100% !important;
    max-width: 100% !important;
  }
  ::v-deep(.el-input-number) {
    width: 200px !important;
    max-width: 100% !important;
  }
}
</style>
<style>
.avatar-uploader .el-upload {
  border: 1px dashed var(--el-border-color);
  border-radius: 6px;
  cursor: pointer;
  position: relative;
  overflow: hidden;
  transition: var(--el-transition-duration-fast);
}

.avatar-uploader .el-upload:hover {
  border-color: var(--el-color-primary);
}

.el-icon.avatar-uploader-icon {
  font-size: 28px;
  color: #8c939d;
  width: 178px;
  height: 178px;
  text-align: center;
}
</style>
